import 'dart:async';

import 'package:cave_flutter/common/chat_rtc_manager.dart';
import 'package:cave_flutter/utils/whl_user_utils.dart';
import 'package:event_bus/event_bus.dart';
import 'package:nim_core/nim_core.dart';
import 'dart:io';

import 'package:path_provider/path_provider.dart';
import 'package:sp_util/sp_util.dart';

import '../utils/event_bus_utils.dart';

String imAppKey = "4e29938c70eacc6b0119f65e17555cf5";

String imAutoAccountKey = "imAutoAccountKey";
String imAutoTokenKey = "imAutoTokenKey";

enum MyCustomMsgType {
  videoCall(1),
  audioCall(2);

  final int tag;
  const MyCustomMsgType(this.tag);
}

class ChatManager {
  static ChatManager? _instance;

  static ChatManager getInstance() {
    if (_instance == null) {
      _instance = ChatManager._internal();
      _instance!.initIMSDK();
    }
    return _instance!;
  }

  ChatManager._internal();

  NIMSDKOptions? options;
  StreamSubscription<NIMAuthStatusEvent>? subscription;
  StreamSubscription<List<NIMMessage>>? messageSubscription;
  StreamSubscription? customNotificationSubscription;
  MessageService messageService = NimCore.instance.messageService;

  initIMSDK() async {
    var account = SpUtil.getString(imAutoAccountKey) ?? "";
    var token = SpUtil.getString(imAutoTokenKey) ?? "";
    if (Platform.isAndroid) {
      final directory = await getExternalStorageDirectory();
      var config = NIMStatusBarNotificationConfig();
      options = NIMAndroidSDKOptions(
          appKey: imAppKey,
          shouldSyncStickTopSessionInfos: true,
          autoLoginInfo: token.isNotEmpty
              ? NIMLoginInfo(account: account, token: token)
              : null,
          notificationConfig: config,
          sdkRootDir: directory != null ? '${directory.path}/NIMCave' : null);
    } else if (Platform.isIOS) {
      final directory = await getApplicationDocumentsDirectory();
      options = NIMIOSSDKOptions(
        appKey: imAppKey,
        shouldSyncStickTopSessionInfos: true,
        sdkRootDir: '${directory.path}/NIMCave',
        autoLoginInfo: token.isNotEmpty
            ? NIMLoginInfo(account: account, token: token)
            : null,
      );
    } else {
      options = NIMWINDOWSSDKOptions(
        appKey: imAppKey,

        /// 其他基础通用配置参数
      );
    }
    NimCore.instance.initialize(options!).then((result) {
      if (result.isSuccess) {
        /// 初始化成功
        print("IM SDK初始化成功");
        addSubscription();
      } else {
        /// 初始化失败
        print("IM SDK初始化失败");
      }
    });
  }

  addSubscription() {
    /// 开始监听事件
    subscription = NimCore.instance.authService.authStatus.listen((event) {
      if (event is NIMKickOutByOtherClientEvent) {
        /// 监听到被踢事件
      } else if (event is NIMAuthStatusEvent) {
        /// 监听到其他事件
        if (event.status == NIMAuthStatus.forbidden ||
            event.status == NIMAuthStatus.kickOut ||
            event.status == NIMAuthStatus.kickOutByOtherClient ||
            event.status == NIMAuthStatus.versionError ||
            event.status == NIMAuthStatus.pwdError) {
          /// 被禁用、被踢、被其他端踢、版本错误、密码错误
          logoutIM();
        }
      }

      if (event is NIMDataSyncStatusEvent) {
        /// 监听到数据同步事件
        if (event.status == NIMAuthStatus.dataSyncStart) {
          /// 数据同步开始
        } else if (event.status == NIMAuthStatus.dataSyncFinish) {
          /// 数据同步完成
        }
      }
    });

    /// 不再监听时，需要取消监听，否则造成内存泄漏
    /// subscription.cancel();
  }

  loginIM(String account, String token) async {
    // var imAutoToken = SpUtil.getString(imAutoTokenKey) ?? "";
    // if (imAutoToken.isNotEmpty) {
    //   return;
    // }
    if (account.isEmpty) {
      account = SpUtil.getString(imAutoAccountKey) ?? "";
      token = SpUtil.getString(imAutoTokenKey) ?? "";
    }
    NimCore.instance.authService
        .login(NIMLoginInfo(
      account: account,
      token: token,
    ))
        .then(
      (result) {
        if (result.isSuccess) {
          /// 登录成功
          /*{
"token": "e0b08f5adf416cf91f084b2f751d9459",
"acid": "17057639733480000000022",
"netAppKey": "4e29938c70eacc6b0119f65e17555cf5"
}*/
          Map dic = result.toMap();
          print(dic);
          print("IM登录成功");
          print(account);
          SpUtil.putString(imAutoAccountKey, account);
          SpUtil.putString(imAutoTokenKey, token);
          addMessageListener();
        } else {
          /// 登录失败
          print("IM登录失败 ${result.code} ${result.errorDetails}");
        }
      },
    );
  }

  logoutIM() {
    SpUtil.remove(imAutoTokenKey);
    SpUtil.remove(imAutoAccountKey);
    subscription?.cancel();
    messageSubscription?.cancel();
    NimCore.instance.authService.logout();
  }

  sendMessageToIM({required NIMMessage message,bool? resend = false}){
    // 自定义消息配置选项
    NIMCustomMessageConfig config =
    NIMCustomMessageConfig(enableRoaming:true,);
    message.config = config;
    Map<String, dynamic> msgExtern = {"avatar":WhlUserUtils.getAvatar(),"nickName":WhlUserUtils.getNickName()};
    message.remoteExtension = msgExtern;
    messageService.sendMessage(message: message, resend: resend??false);
  }

  getImAccountId(){
    return SpUtil.getString(imAutoAccountKey);
  }

  getImAppKey(){
    return imAppKey;
  }

  addMessageListener() {

    messageSubscription = NimCore.instance.messageService.onMessage.listen((List<NIMMessage> list) {
      // 处理新收到的消息，为了上传处理方便，SDK 保证参数 messages 全部来自同一个聊天对象。
      list.forEach((element) {
        if (element.messageType == NIMMessageType.custom) {
          Map<String, dynamic>? a = element.messageAttachment?.toMap();
          int customType = a?["customType"] ??0;
          if (customType == MyCustomMsgType.videoCall.tag ||customType == MyCustomMsgType.audioCall.tag) {
            Map<String, dynamic>? a = element.messageAttachment?.toMap();
            int actionType = a?["actionType"]??0;
            if (actionType != -1) {
              int timestamp = DateTime.now().millisecondsSinceEpoch - element.timestamp;
              print("111timestamp $timestamp -- ${DateTime.now().millisecondsSinceEpoch}--${element.timestamp}");
              if (timestamp > 60*1000) {
                return;
              }
              getRTCToken(a?["channelName"]??"",toAccountId: element.sessionId,isReceive: true,isVideoCall: customType == MyCustomMsgType.videoCall.tag);
            }else {
              RtcStatus rtcStatus = RtcStatus(-1, []);
              EventBusUtils.getInstance().eventBus.fire(rtcStatus);
              ChatRTCManager.getInstance().stopCall();
            }
            // if (!ChatRTCManager.getInstance().isCallIng) {

            // }
          }
        }
        EventBusUtils.getInstance().eventBus.fire(element);
      });
    });

    customNotificationSubscription = NimCore.instance.systemMessageService.onCustomNotification.listen((CustomNotification event) {
      EventBusUtils.getInstance().eventBus.fire(event);
    });
  }
}
